// $Id: ast.c 28 2015-03-11 01:53:12Z robim.poa@gmail.com $
//-----------------------------------------------------------------------------
// Purpose: Abstract syntax tree related functions
// $Rev: 28 $
// $Author: robim.poa@gmail.com $
// $Date: 2015-03-11 01:53:12 +0000 (Wed, 11 Mar 2015) $

#include <stdio.h>
#include <stdlib.h>

#include "debug.h"
#include "ast.h"
#include "expression.h"

struct node_ast* astCreateNode(int func, int value)
{
	struct node_ast *node_ast_new = (struct node_ast*) malloc(sizeof(struct node_ast));
	node_ast_new->left  = NULL;
	node_ast_new->right = NULL;
	node_ast_new->func  = func;
	node_ast_new->value = value;

	return node_ast_new;
}

void astPrint(struct node_ast *node_ast)
{
	astPrintRecurse(node_ast, 0);
}

void astPrintRecurse(struct node_ast *node_ast, int depth)
{
	if(node_ast != NULL)
	{
		printf("%s [%f]\n", astFuncToString(node_ast->func),node_ast->value);
		depth++;

		astPrintTabs(depth);
		printf("|- (right) ");
		astPrintRecurse(node_ast->right, depth);

		astPrintTabs(depth);
		printf("|- (left)  ");
		astPrintRecurse(node_ast->left, depth);
	}
	else
		printf("\n");
}

void astPrintTabs(int x)
{
	int i;
	for(i=0; i<x; i++)
		printf("|  ");
}

int astOperatorToFunc(int operator)
{
	switch(operator)
	{
		case LOGIC_OPERATOR_OR:
			return AST_OR;

		case LOGIC_OPERATOR_AND:
			return AST_AND;

		case LOGIC_OPERATOR_NOT:
			return AST_NOT;

		case COMPARISON_OPERATOR_EQUAL:
			return AST_EQUAL;

		case COMPARISON_OPERATOR_NEQUAL:
			return AST_NEQUAL;

		case COMPARISON_OPERATOR_GREATER:
			return AST_GREATER;

		case COMPARISON_OPERATOR_LESS:
			return AST_LESS;

		case COMPARISON_OPERATOR_GREATER_EQUAL:
			return AST_GEQUAL;

		case COMPARISON_OPERATOR_LESS_EQUAL:
			return AST_LEQUAL;

		case ARITHMETIC_OPERATOR_EQUAL:
			return AST_ASSIGN;

		case ARITHMETIC_OPERATOR_PLUS:
			return AST_PLUS;

		case ARITHMETIC_OPERATOR_MINUS:
			return AST_MINUS;

		case ARITHMETIC_OPERATOR_MULTI:
			return AST_MULTI;

		case ARITHMETIC_OPERATOR_DIVIS:
			return AST_DIVIS;

		case ARITHMETIC_OPERATOR_MODULO:
			return AST_MODULO;

		case ARITHMETIC_OPERATOR_POWER:
			return AST_POWER;

		default:
			return AST_NONE;
	}
}

const char* astFuncToString(int ast_func)
{
	switch(ast_func)
	{
		case AST_OR:
			return "Or";
		case AST_AND:
			return "And";
		case AST_NOT:
			return "Not";
		case AST_EQUAL:
			return "Eql";
		case AST_NEQUAL:
			return "NEql";
		case AST_GREATER:
			return "Grt";
		case AST_LESS:
			return "Les";
		case AST_GEQUAL:
			return "GEql";
		case AST_LEQUAL:
			return "LEql";
		case AST_ASSIGN:
			return "Asg";
		case AST_PLUS:
			return "Add";
		case AST_MINUS:
			return "Sub";
		case AST_MULTI:
			return "Mul";
		case AST_DIVIS:
			return "Div";
		case AST_MODULO:
			return "Mod";
		case AST_POWER:
			return "Pow";
		case AST_FUNC:
			return "Fnc";
		case AST_WHILE:
			return "While";
		case AST_COMPARE:
			return "Cmp";
		case AST_FOR:
			return "For";
		case AST_IF:
			return "If";
		case AST_ELSE:
			return "Els";
		case AST_VALUE:
			return "Val";
		case AST_VAR:
			return "Var";
		case AST_BODY:
			return "Bdy";
		default:
			return "MISSING";
	}
}